出处:掘金

原作者:金泽宸


面试必问:你能手写 instanceof 吗?

面试官为什么问这个问题:

工作原理(基于原型链)

a instanceof B 本质判断的是:B.prototype 是否在 a.__proto__ 的原型链上。即:

a.__proto__ === B.prototype
a.__proto__.__proto__ === B.prototype
a.__proto__.__proto__.__proto__ === B.prototype
// ...
// 直到 __proto__ === null 为止

注意事项

console.log('str' instanceof String); // false,需用 new String() 创建对象
({}) instanceof null; // Uncaught TypeError: Right-hand side of 'instanceof' is not an object

手写 instanceof

function myInstanceof(obj, constructor) {
  if (typeof obj !== 'object' || obj === null) return false;
  if (typeof constructor !== 'object' || constructor === null) {
    throw new TypeError(`Right-hand side of 'instanceof' is not an object`);
  }

  let proto = Object.getPrototypeOf(obj); // 相当于 obj.__proto__
  const prototype = constructor.prototype;

  while (proto) { // 当proto == null 时,说明已经找到了 Object 的基类 null,退出循环
    if (proto === prototype) return true;
    proto = Object.getPrototypeOf(proto); // 向上查找
  }
  return false;
}

常见易错点

易错点 正解
忘了处理 null typeof obj !== 'object' || obj === null
直接 __proto__ 推荐用 Object.getPrototypeOf() 更规范
判断条件错误 proto === constructor.prototype,不要搞混

进阶加分项

实际上 a instanceof B 会调用:

B[Symbol.hasInstance](a)

你甚至可以这样 hack:

class A {
  static [Symbol.hasInstance](obj) {
    return false;
  }
}
console.log(new A() instanceof A); // false !!!

这是 instanceof 可被重写的入口,了解这个能在面试中加分